package com.sxj.corejava.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @author 石小俊
 * @date 2024年04月16日 18:26
 * 日期工具类
 */
public class DateUtil {

    /**
     * 将日期转换成字符串
     * @param date    需要转换的日期值
     * @param pattern 指定的字符串格式
     * @return 转换后的字符串
     */
    public static String toString(Date date, String pattern) {
        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 将日期转换成默认格式的字符串
     * @param date 需要转换的日期值
     * @return 转换后的字符串
     * @see DateConstant
     */
    public static String toString(Date date) {
        return DateUtil.toString(date, DateConstant.DATE_DEFAULT_PATTERN);
    }

    /**
     * 将指定格式的字符串转换成日期
     * @param str     转换前的字符串
     * @param pattern 指定的字符串格式
     * @return 转换后的日期值
     */
    public static Date toDate(String str, String pattern) throws ParseException {
        return new SimpleDateFormat(pattern).parse(str);
    }

    /**
     * 将默认格式的字符串转换成日期
     * @param str 转换前的字符串
     * @return 转换后的日期值
     * @see DateConstant
     */
    public static Date toDate(String str) throws ParseException {
        return DateUtil.toDate(str, DateConstant.DATE_DEFAULT_PATTERN);
    }

    /**
     * 获取指定日期的前一天
     * @param date
     * @return
     */
    public static Date getYesterday(Date date) {
        long time = date.getTime() - DateConstant.ONE_DAY_MILLISECONDS;
        return new Date(time);
    }

    /**
     * 获取指定日期的下一天
     * @param date
     * @return
     */
    public static Date getNextDay(Date date) {
        long time = date.getTime() + DateConstant.ONE_DAY_MILLISECONDS;
        return new Date(time);
    }

    /**
     * 计算两个日期之间相差的天数
     * @param startDate 开始日期
     * @param endDate   结束日期
     */
    public static int getDuringDay(Date startDate, Date endDate) {
        long time = endDate.getTime() - startDate.getTime();
        int day = (int) (time / DateConstant.ONE_DAY_MILLISECONDS);
        return day;
    }

    /**
     * 获取日期中指定的年、月、日、时、分、秒的值
     * 对应字段可以设置为常量
     * 根据传递的常量参数不同,返回日期中不同部分的值
     * @param date  指定日期
     * @param field 指定需要获取的字段是谁
     * @return
     * @see DateConstant
     */
    public static int get(Date date, int field) {
        // 将日期转换成指定格式的字符串
        String s = toString(date, "yyyy-MM-dd HH:mm:ss");
        // 通过-或者空格或者冒号进行分割,将字符串分割成数组
        // 通过正则表达式进行分割
        String[] arr = s.split("-|\\s|:");
        // 此时数组元素的下标与field对应常量一致
        // 下标为0的对应年,下标为1的对应月...
        return Integer.parseInt(arr[field]);
    }

    /**
     * 根据指定的年份与月份,获取对应月份中共有多少天
     * 通过日历类提供的方法实现
     * @param year
     * @param month
     * @return
     */
    public static int getDay(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置日历的年份
        calendar.set(Calendar.YEAR, year);
        // 设置日历的月份
        calendar.set(Calendar.MONTH, month - 1);
        // 获取对应日历这个月共有多少天
        return calendar.getActualMaximum(Calendar.DATE);
    }

    /**
     * 根据指定的年份与月份,获取对应月份中共有多少天
     * 通过通用的逻辑来实现
     * @param year
     * @param month
     * @return
     */
    public static int getDay2(int year, int month) {
        // 假设我们指定了一个日期,这个日期表示的是这一年这个月的最后一天
        // 在这一天通过方法获取当前是这个月的第几天
        // 当前是第几天,则表示这个月共有多少天
        // 如何将日期的值设置为year年month月的最后一天呢?
        // 虽然无法直接设置这一天的日期值,但是我一定能够设置下一天的值
        // 下一天为:year年month+1月1日
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1 + 1);
        calendar.set(Calendar.DATE, 1);
        // 这一天的前一天,即为本月最后一天
        // 对于日期的值,是支持运算的,通过天数进行运算
        calendar.add(Calendar.DATE, -1);
        return calendar.get(Calendar.DATE);
    }
}
